package controller.transform;

import javax.swing.SwingUtilities;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Vector3d;

import math.Precision;
import math.Vectors;

import component.Tube;
import component.group.ComponentGroup;

public class AlignAngleAxis extends AlignAngle {

	private final Tube axis;
	private final double angle;
	
	public AlignAngleAxis(Gui gui, Scene scene, Tube axis, double angle) {
		super(gui, scene, axis);
		this.axis = axis;
		this.angle = angle;
	}

	@Override
	protected void tryToAlign(final ComponentGroup group, final Vector3d referenceVector,
			final Vector3d alignVector) {
		
		if (Precision.compare(referenceVector.angle(alignVector), angle) || Precision.compare(referenceVector.angle(alignVector), -angle)) {
			gui.setStatusText("Already aligned correctly.");
			return;
		}
		
		final Vector3d rotationAxis = axis.getOrientation().getVector();
		
		if (gui.getCameraPosition().distance(axis.getPos()) > gui.getCameraPosition().distance(axis.getSecondaryPosition())) {
			rotationAxis.negate();
		}
		gui.setStatusText("Calculating....");
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				doCalculations(group, referenceVector, alignVector, rotationAxis);				
			}
			
		});
	}

	private void doCalculations(final ComponentGroup group,
			final Vector3d referenceVector, final Vector3d alignVector,
			final Vector3d rotationAxis) {
		Double rotate = Vectors.findAngle(alignVector, referenceVector, angle, rotationAxis);
		
		if (rotate == null) {
			gui.setStatusText("Unable to detect possible way to align correctly.");
			return;
		}
		
		AxisAngle4d axisAngle = new AxisAngle4d(rotationAxis, rotate);
		
		this.alignGroup(group, axisAngle, connectionBall.getPos());
	}


}
